use core::slice;

fn main() {
    let mut num = 5;

    let r1 = &num as *const i32;
    let r2 = &mut num as *mut i32;

    unsafe 
    {
        println!("r1: {}", *r1);
        println!("r2: {}", *r2);
    }

    let address = 0x012345usize;
    let r = address as *mut i32;

    let slice： &[i32] = unsafe {
        slice::from_raw_parts_mut(r, 10000)
    };

    // 为什么要用原始指针？
    // - 与C语言进行接口
    // - 构建借用检查器无法理解的安全抽象

    unsafe 
    {
        dangerous();
        println!("C: {}", abs(-3));
    }

    let mut v = vec![1,2,3,4,5,6];

    let r = &mut  v[..];
    let (a, b) = r.split_at_mut(3);
    assert_eq!(a, &mut [1,2,3]);
    assert_eq!(b, &mut [4,5,6]);

    add_to_count(3);

    unsafe {
        println!("COUNTER: {}", COUNTER);
    }


    let w = Wrapper(vec![String::from("hello"),String::from("world")]);
    println!("{}",w);

    let x = 5;
    let y: Kilometers = 5;
    println!("x + y = {}", x + y);

    // 原始
    let f: Box<dyn Fn() + Send + 'static> = Box::new(|| println!("hi"));

    // 使用别名后
    let f: Thunk = Box::new(|| println!("hi"));
}

type Thunk = Box<dyn Fn() + Send + 'static>;

unsafe fn dangerous() {
    println!("hello world!")
}

// fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
//     let len = slice.len();
//      assert!(mid <= len);
//      (&mut slice[..mid], &mut slice[mid..])
// }


fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = slice.len();
    let ptr = slice.as_mut_ptr();

    assert!(mid <= len);

    unsafe {{
        slice::from_raw_parts_mut(ptr, mid),
        slice::from_raw_parts_mut(ptr.add(mid), len - mid),
    }}
}

extern "C" {
    fn abs(input: i32) -> i32;
}

#[no_mangle]
pub extern "C" fn call_from_c() {
    println!("just call a rust function from c");
}

static mut COUNTER: i32 = 0;

fn add_to_count(inc: u32) {
    unsafe {
        COUNTER += inc;
    }
}

pub trait Iterator {
    // 类型别名
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}


use std::ops::Add;

struct Millmeters(u32);
struct Meters(u32);

impl Add<Meters> for Millmeters {
    type Output = Millmeters;

    fn add(self,other: Meters) {
        Millmeters(self.0 + (other.0 * 1000))
    }
}


use std::fmt; 

trait OutlinePrint: fmt::Display {
    fn outline_print(&self) {
        let output = self.to_string();
        let len = output.len();
    }
}

// 绕过孤儿原则
struct  Wrapper(Vec<String>);

impl fmt::Display for Wrapper {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"[{}]",self.0.join(", "))
    }
}

type Kilometers = i32;


fn takes_long_type(f: Thunk) {
}

fn return_long_type(f: Thunk) {
    Box::new(|| println!("hi"));
}


fn add_one(x: i32) -> i32 {
    x + 1
}

fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32{
    f(arg) + f(arg)
}


